package com.doge.walknovel.api

import androidx.lifecycle.LifecycleOwner
import com.doge.wnpro.BuildConfig
import com.doge.walknovel.utils.FileUtils
import com.doge.walknovel.utils.isTestEnv
import com.doge.walknovel.utils.log
import com.doge.walknovel.utils.serviceUrl
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import okhttp3.Cache
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.Executors

private val retrofit: Retrofit
    get() {
        val loggingInterceptor = HttpLoggingInterceptor { log(it, "novel-http") }
        loggingInterceptor.level =
            if (isTestEnv || BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE

        val builder = OkHttpClient.Builder()
            .addInterceptor(loggingInterceptor)
            .addInterceptor(ReqRespInterceptor())
            .retryOnConnectionFailure(false)
            .cache(Cache(FileUtils.filesDir("httpCache"), 52428800L)) // 50 * 1024 * 1024

        val client = builder.build()
        return Retrofit.Builder()
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create())
            .baseUrl(serviceUrl)
            .client(client)
            .build()
    }

val api by lazy { retrofit.create(ApiService::class.java) }

val workThreadPool by lazy { Executors.newSingleThreadExecutor()!! }
val workScheduler = Schedulers.from(workThreadPool)

fun <T> Observable<T>.subscribeOnIO(): Observable<T> = subscribeOn(Schedulers.io())
fun <T> Observable<T>.observeOnMain(): Observable<T> = observeOn(AndroidSchedulers.mainThread())
fun <T> Observable<T>.observeOnWork(): Observable<T> = observeOn(workScheduler)

fun Disposable.bindLifecycle(owner: LifecycleOwner?) = this.apply {
    val lifecycle = owner?.lifecycle
    lifecycle?.let { it.addObserver(LifecycleObserver(it, this)) }
}